﻿using DynamicPatcher;
using Extension.Utilities;
using PatcherYRpp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace Extension.Ext
{


    [Serializable]
    public class PassengerExtensionData
    {
        public bool AlwaysSync = false;

        public List<string> InitPassengers = null;

        public List<int> PassengerNums = null;

        public PassengerExtensionData(bool alwaysSync)
        {
            AlwaysSync = alwaysSync;
        }

    }



    public partial class TechnoExt
    {
        private int passengerCheckDelay = 20;

        private int lastHouseIndex = -1;

        private bool passengerInited = false;

        public unsafe void TechnoClass_Update_Passenger_Extension()
        {
            PassengerExtensionData data = this.Type.PassengerExtensionData;

            if (data == null)
                return;

            if (!data.AlwaysSync)
                return;

            if (passengerCheckDelay-- > 0)
                return;

            passengerCheckDelay = 20;

            if (OwnerObject.Ref.Owner.IsNull)
                return;

            if (OwnerObject.Ref.Passengers.NumPassengers == 0 && data.InitPassengers != null && !passengerInited)
            {
                //数量不一致说明ini写错了
                if (data.InitPassengers.Count == data.PassengerNums.Count)
                {
                    //添加乘客
                    if (data.InitPassengers.Count > 0)
                    {
                        for (var i = 0; i < data.InitPassengers.Count(); i++)
                        {
                            var typeStr = data.InitPassengers[i];
                            var num = data.PassengerNums[i];

                            var technoType = TechnoTypeClass.ABSTRACTTYPE_ARRAY.Find(typeStr);

                            if (technoType != null)
                            {
                                for (var j = num; j > 0; j--)
                                {
                                    var techno = technoType.Ref.Base.CreateObject(OwnerObject.Ref.Owner).Convert<TechnoClass>();
                                    if (techno == null)
                                        continue;

                                    techno.Ref.Base.SetLocation(OwnerObject.Ref.Base.Base.GetCoords());
                                    techno.Ref.Base.Remove();

                                    //这里要加个判断OpenTopped 这里没写因为一般用到的时候都是需要乘员开火的情况
                                    OwnerObject.Ref.EnteredOpenTopped(techno);

                                    if (techno.CastToFoot(out var pfoot))
                                    {
                                        OwnerObject.Ref.Passengers.AddPassenger(pfoot);
                                    }
                                }
                            }
                        }
                    }

                    passengerInited = true;
                }
            }
            else
            {
                passengerInited = true;
            }

            var currentHouse = OwnerObject.Ref.Owner;

            if (lastHouseIndex == -1)
            {
                lastHouseIndex = currentHouse.Ref.ArrayIndex;
                return;
            }

            if (currentHouse.Ref.ArrayIndex != lastHouseIndex)
            {
                //更改载员所属
                List<Pointer<FootClass>> passengers = new List<Pointer<FootClass>>();

                while (!OwnerObject.Ref.Passengers.GetFirstPassenger().IsNull)
                {
                    var passenger = OwnerObject.Ref.Passengers.GetFirstPassenger();
                    if (passenger.Convert<AbstractClass>().CastToTechno(out Pointer<TechnoClass> pPassenger))
                    {
                        passengers.Insert(0, passenger);
                        OwnerObject.Ref.Passengers.RemoveFirstPassenger();
                        pPassenger.Ref.Owner = currentHouse;
                    }
                }

                foreach (var passenger in passengers)
                {
                    OwnerObject.Ref.Passengers.AddPassenger(passenger);
                }
            }

            lastHouseIndex = currentHouse.Ref.ArrayIndex;
        }



        public unsafe void TechnoClass_Passenger_InTransport_Extension()
        {
            Pointer<TechnoClass> pTechno = OwnerObject;
            Pointer<TechnoClass> pTransporter = pTechno.Ref.Transporter;
            if (!pTransporter.IsNull)
            {
                TechnoExt transporterExt = TechnoExt.ExtMap.Find(pTransporter);
                if (transporterExt.Type.OpenTopped == false)
                    return;

                if (transporterExt.Type.OpenToppedAffectTarget == "all" || string.IsNullOrEmpty(transporterExt.Type.OpenToppedAffectTarget))
                    return;

                if (transporterExt != null)
                {
                    if (transporterExt.OwnerObject.Ref.Target.IsNull)
                        return;

                    var target = transporterExt.OwnerObject.Ref.Target;
                    if (target.CastToTechno(out var ptarget))
                    {
                        if (ptarget.Ref.Owner.IsNull)
                            return;

                        if (pTransporter.Ref.Owner.IsNull)
                            return;

                        var isAllied = ptarget.Ref.Owner.Ref.IsAlliedWith(pTransporter.Ref.Owner);

                        if ((isAllied && transporterExt.Type.OpenToppedAffectTarget == "enermy") || (!isAllied && transporterExt.Type.OpenToppedAffectTarget == "ally"))
                        {
                            pTechno.Ref.SetTarget(default);
                            pTechno.Convert<MissionClass>().Ref.ForceMission(Mission.Stop);
                        }
                    }
                }
            }
        }

    }

    public partial class TechnoTypeExt
    {
        public PassengerExtensionData PassengerExtensionData;

        public string OpenToppedAffectTarget = "all";

        public bool OpenTopped = false;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="section"></param>
        private void ReadPassengerExtensionData(INIReader reader, string section)
        {
            if (PassengerExtensionData == null)
            {
                reader.ReadNormal(section, "OpenTopped.AffectTarget", ref OpenToppedAffectTarget);
                reader.ReadNormal(section, "OpenTopped", ref OpenTopped);


                bool alwaysSync = false;
                if (reader.ReadNormal(section, "Passenger.AlwaysSync", ref alwaysSync))
                {
                    PassengerExtensionData = new PassengerExtensionData(alwaysSync);

                    if (alwaysSync)
                    {
                        string types = string.Empty;
                        if (reader.ReadNormal(section, "InitialPayload.Types", ref types))
                        {
                            if (!string.IsNullOrEmpty(types))
                            {
                                PassengerExtensionData.InitPassengers = types.Split(',').ToList();
                            }
                        }

                        string nums = string.Empty;
                        if (reader.ReadNormal(section, "InitialPayload.Nums", ref nums))
                        {
                            if (!string.IsNullOrEmpty(nums))
                            {
                                PassengerExtensionData.PassengerNums = nums.Split(',').Select(x => Int32.Parse(x)).ToList();
                            }
                        }
                    }
                }
                else
                {
                    PassengerExtensionData = new PassengerExtensionData(alwaysSync);
                }

            }

        }
    }
}
